import { Cascader, CascaderProps, Form } from 'antd';
import React, { useState } from 'react';

export interface CascaderOption {
  label: React.ReactNode;
  value?: string | number | null;
  children?: CascaderOption[];
  isLeaf?: boolean;
  loading?: boolean;
}

export type ILoadDataFn = {
  value: string | number;
  callback: (res: CascaderOption[]) => void;
};

type Props = CascaderProps<CascaderOption> & {
  options: CascaderOption[];
  disabled?: boolean;
  placeholder?: string;
  onChange: (value: (string | number)[], selectedOptions: CascaderOption[]) => void;
  loadDataFn: (params: ILoadDataFn) => void;
};

const SuperCascader: React.FC<Props> = (props) => {
  const { options, disabled, placeholder, onChange, loadDataFn } = props;
  const [dataSource, setDataSource] = useState<CascaderOption[]>(options);

  const filter = (inputValue: string, path: CascaderOption[]) => {
    return path.some((option) => (option.label as string).toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
  };

  // 动态加载数据（第一次选择更改时会触发此函数，已加载过的不会再次触发）
  const handleLoadData = (selectedOptions: CascaderOption[]) => {
    const targetOption: CascaderOption = selectedOptions[selectedOptions.length - 1];
    // 加载标识
    targetOption.loading = true;

    // 选择业务线时获取项目、数据库时获取数据库表
    if (targetOption.value && loadDataFn) {
      loadDataFn({
        value: targetOption.value,
        callback: (resData: CascaderOption[]) => {
          // load options lazily
          setTimeout(() => {
            // 取消加载标识
            targetOption.loading = false;
            // 把下级数据存进去
            targetOption.children = resData;
            // 重新赋值级联数据
            setDataSource([...dataSource]);
          }, 300);
        },
      });
    }
  };

  const handleChange = (value: (string | number)[], selectedOptions: CascaderOption[]) => {
    if (onChange) {
      onChange(value, selectedOptions);
    }
  };

  return (
    <Form.Item label="Username">
      <Cascader
        changeOnSelect
        placeholder={placeholder}
        disabled={disabled}
        showSearch={{ filter }}
        options={dataSource}
        loadData={handleLoadData}
        onChange={handleChange}
        onSearch={(value) => console.log(value)}
      />
    </Form.Item>
  );
};

export default SuperCascader;
